package com.alibaba.citrus.cr.unified.inventory.facade.service;

import com.alibaba.citrus.cr.unified.inventory.repository.InvoiceOrderReadRepository;
import com.alibaba.citrus.cr.unified.inventory.utils.InfoUtil;
import com.alibaba.citrus.cr.unified.inventory.utils.OtsDateUtils;
import com.alibaba.citrus.cr.common.annotation.EpochTransactional;
import com.alibaba.citrus.cr.common.exception.FacadeException;
import com.alibaba.citrus.cr.common.util.SapAndCrmFieldDealUtils;
import com.alibaba.citrus.cr.common.util.TimeUtil;
import com.alibaba.citrus.cr.unified.inventory.functions.invoiceOrder.InvoiceOrderDetailEntity;
import com.alibaba.citrus.cr.unified.inventory.functions.invoiceOrder.InvoiceOrderEntity;
import com.alibaba.citrus.cr.unified.inventory.functions.invoiceOrder.InvoiceOrderFactory;
import com.alibaba.citrus.cr.unified.inventory.validator.InvoiceOrderValidator;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.lattice2.epoch.middleware.mq.runtime.EpochMessageService;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcorder.service.BaseDataService;
import com.epoch.app.crb2btradecenter.api.orderlinewrite.service.OrderLineWriteService;
import com.epoch.app.crb2btradecenter.api.orderquery.service.OrderQueryService;
import com.epoch.app.crb2btradecenter.dto.response.OrderPageQueryResponse;
import com.epoch.app.crb2btradecenter.model.dto.PageQueryOrderEsListRequest;
import com.epoch.app.crunifiedinventory.api.allocateorderread.service.AllocateOrderReadService;
import com.epoch.app.crunifiedinventory.api.allocateorderwrite.service.AllocateOrderWriteService;
import com.epoch.app.crunifiedinventory.api.invoiceorderwrite.service.InvoiceOrderWriteService;
import com.epoch.app.crunifiedinventory.domain.allocateorder.dto.AllocateOrderLoadListRequest;
import com.epoch.app.crunifiedinventory.domain.allocateorder.model.AllocateOrder;
import com.epoch.app.crunifiedinventory.domain.allocateorder.service.AllocateOrderService;
import com.epoch.app.crunifiedinventory.domain.invoiceorderdetail.model.InvoiceOrderDetail;
import com.epoch.app.crunifiedinventory.domain.invoiceorderdetail.service.InvoiceOrderDetailService;
import com.epoch.app.crunifiedinventory.dto.request.InvoiceOrderCreateRequest;
import com.epoch.app.crunifiedinventory.dto.response.AllocateOrderDetailBatchGetScItemResponse;
import com.epoch.app.crunifiedinventory.model.dto.*;
import com.epoch.app.crunifiedinventory.sdo.InvoiceOrderDetailSDO;
import com.epoch.app.crunifiedinventory.sdo.InvoiceOrderSDO;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;

@Component
@Primary
public class InvoiceOrderWriteServiceImpl implements InvoiceOrderWriteService {
    @Autowired
    private InvoiceOrderDetailService invoiceOrderDetailService;
    @Autowired
    private InvoiceOrderReadRepository invoiceOrderReadRepository;
    @Autowired
    private AllocateOrderWriteService allocateOrderWriteService;
    @Autowired
    AllocateOrderReadService allocateOrderReadService;
    @Resource
    private  EpochMessageService messageService;
    @Resource
    private OrderQueryService orderQueryService;
    @Resource
    private AllocateOrderService allocateOrderService;


    private final Log log = Log.getLogger(InvoiceOrderWriteServiceImpl.class);
    @Override
    public Result<Boolean> createInvoiceOrder(InvoiceOrderCreateRequest request) {
        log.info("InvoiceOrderWriteServiceImpl createInvoiceOrder "+JSON.toJSONString(request));
        //参数校验
        InvoiceOrderValidator.check(request);

        // 源单id  创建时间
        String sourceOrderId = request.getSourceOrderId();
        if (StringUtils.isNotBlank(sourceOrderId)) {
            // 根据源单id 查询 源单的创建时间 可能是对应销售单的，也可能对应调拨单的

            // 查询销售单是否存在
            PageQueryOrderEsListRequest pageQueryOrderEsListRequest = new PageQueryOrderEsListRequest();
            pageQueryOrderEsListRequest.setOuterId(sourceOrderId);
            Result<List<OrderPageQueryResponse>> listResult = orderQueryService.pageQueryOrderListES(pageQueryOrderEsListRequest);
            if (listResult != null && listResult.isSuccess() && !CollectionUtils.isEmpty(listResult.getResult())) {
                OrderPageQueryResponse orderPageQueryResponse = listResult.getResult().get(0);
                request.setSourceOrderCreateTime(OtsDateUtils.parseDate(orderPageQueryResponse.getOrderTime(), "yyyy-MM-dd HH:mm:ss"));
            }
            // 查询调拨单是否存在
            AllocateOrderLoadListRequest allocateOrderLoadListRequest = new AllocateOrderLoadListRequest();
            allocateOrderLoadListRequest.setOutAllocateOrderId(sourceOrderId);
            Result<List<AllocateOrder>> loadAllocateOrderList = allocateOrderService.loadAllocateOrderList(allocateOrderLoadListRequest);
            if (loadAllocateOrderList != null && !CollectionUtils.isEmpty(loadAllocateOrderList.getResult())) {
                AllocateOrder allocateOrder = loadAllocateOrderList.getResult().get(0);
                request.setSourceOrderCreateTime(allocateOrder.getGmt_create());
            }
        }

        InvoiceOrderEntity entity = InvoiceOrderFactory.create(request);
        entity.add();
        //发送创建消息消息，订单接收
        try {
            InvoiceOrderSDO invoiceOrderSDO = entity.getInvoiceOrderSDO();
            List<InvoiceOrderDetailEntity> invoiceOrderDetailEntityList = entity.getInvoiceOrderDetailEntityList();
            List<InvoiceOrderDetailSDO> invoiceOrderDetailSDOS =invoiceOrderDetailEntityList.stream().map(InvoiceOrderDetailEntity::getInvoiceOrderDetailSDO).collect(Collectors.toList());
            invoiceOrderSDO.setDetailList(invoiceOrderDetailSDOS);

            log.info("InvoiceOrderWriteServiceImpl send_messageKey:" + invoiceOrderSDO.getInvoiceOrderId());
            boolean sendResult = messageService.sendMessage("invoice_order_message", "CR_INVOICE_V2", "InvoiceCreated", String.valueOf(entity.getInvoiceOrderSDO().getInvoiceOrderId()), JSON.toJSONString(invoiceOrderSDO));
            log.info("InvoiceOrderWriteServiceImpl sendResult_messageKey:" + sendResult + invoiceOrderSDO.getInvoiceOrderId());

        } catch (Exception e) {
//            e.printStackTrace();
            log.error("InvoiceOrderWriteServiceImpl send exception messageKey:" + request.getInvoiceOrderId(),e);
        }
        return Result.success(Boolean.TRUE);
    }

    /**
     * 拿退单请求 去获取回显数据
     *
     * @param returnOrderRequest
     * @return
     */
    @Override
    public Result<ReturnOrderReshowResponse> createReturnOrder(ReturnOrderRequest returnOrderRequest) {
        try {
        InnerParam request = packageRequest(returnOrderRequest);
        Result<AllocateOrderReturnOrderInfoResponse> allocateOrderReturnOrderInfoResponseResul =
                allocateOrderReadService.getReturnOrderInfo(request.getAllocateOrderReturnOrderRequest());
        ReturnOrderReshowResponse response = new ReturnOrderReshowResponse();
        response.setReturnOrderCreateRequest(returnOrderRequest);
        response.setAllocatedOrderReshowInfo(allocateOrderReturnOrderInfoResponseResul.getResult());
          return Result.success(response);
        }catch (FacadeException e){
            return  Result.fail(e.getErrorCode(),e.getMessage());
        }
    }

    private Map<String, AllocateOrderDetailBatchGetScItemResponse> getGoodsList(List<InvoiceOrderDetailSDO> items) {
        Set<String> goodsCode = new HashSet<>();
        items.forEach(x -> goodsCode.add(SapAndCrmFieldDealUtils.generateIdField(x.getScItemId())));

        Map<String, AllocateOrderDetailBatchGetScItemResponse> map = InfoUtil.getScItemMapByOutCodes(goodsCode.stream().collect(Collectors.toList()));
        return map;
//        SearchScItemRequest searchScItemRequest = new SearchScItemRequest();
//        Map<String, List<String>> outerIdList = new HashMap<>();
//        outerIdList.put("outerIdList", goodsCode.stream().collect(Collectors.toList()));
//        searchScItemRequest.setSearchReqDTO(outerIdList);
//        Result<List<ScItemSDO>> scItemResult = baseDataService.searchScItem(searchScItemRequest);
//        if (scItemResult == null) {
//            throw new FacadeException("OTS-03-001-00-15-002", goodsCode.toString());
//        }
//        if (CollectionUtils.isEmpty(scItemResult.getResult())) {
//            throw new FacadeException("OTS-03-001-00-15-002", goodsCode.toString());
//        }
//        Map<String, ScItemSDO> scItems = scItemResult.getResult().stream().collect(Collectors.toMap(x -> x.getOuterId(), x -> x, (v1, v2) -> v2));
//        return scItems;
    }

    /**
     * 提交退单请求 并更新数量
     *
     * @param returnOrderRequest
     * @return
     */
    @Override
    @EpochTransactional(appCode="bc_order", dataSourceCode = "cr_ots", dataSourceType = "app")
    public Result<Void> submitReturn(ReturnOrderRequest returnOrderRequest) {
        try {
        InnerParam request = packageRequest(returnOrderRequest);
        Result<AllocateOrderReturnOrderResponse> createResult = allocateOrderWriteService.returnOrder(request.getAllocateOrderReturnOrderRequest());
        if (!createResult.isSuccess()) {
            throw new FacadeException("OTS-03-003-15-006");
        }
        //修改发票货品退货数量
        request.getUpdateOrderDetailList().stream().forEach(x -> {
            InvoiceOrderDetail invoiceOrderDetail = new InvoiceOrderDetail();
            invoiceOrderDetail.setId(x.getId());
            if (Objects.nonNull(x.getReturnQuantity())) {
                invoiceOrderDetail.setReturnQuantity(x.getReturnQuantity());
            }
            invoiceOrderDetail.setGmt_modified(new Date());
            invoiceOrderDetailService.updateInvoiceOrderDetail(invoiceOrderDetail);
        });
            return Result.success(null);
        }catch (FacadeException e){
            return  Result.fail(e.getErrorCode(),e.getMessage());
        }
    }

    /**
     * 包装一下 请求调拨单的请求参数
     *
     * @return
     */
    private InnerParam packageRequest(ReturnOrderRequest returnOrderRequest) {
        InnerParam innerParam = new InnerParam();
        List<ReturnOrderGoodsInfo> returnOrderGoodsInfos = returnOrderRequest.getReturnGoodsList();
        if (CollectionUtils.isEmpty(returnOrderGoodsInfos)) {
            throw new FacadeException("OTS-03-003-15-002");
        }
        InvoiceOrderSDO invoiceMainOrder = invoiceOrderReadRepository.queryInvoiceOrderById(returnOrderRequest.getInvoiceId());
        List<InvoiceOrderDetailSDO> item = invoiceMainOrder.getDetailList();
        if (CollectionUtils.isEmpty(item)) {
            throw new FacadeException("OTS-03-003-15-004");
        }
        //发票明细map
        Map<Long, InvoiceOrderDetailSDO> itemMap = item.stream().collect(Collectors.toMap(InvoiceOrderDetailSDO::getId, o -> o, (k1, k2) -> k1));
        //货品 提取goodsId 外部code用
        Map<String, AllocateOrderDetailBatchGetScItemResponse> goodsList = getGoodsList(item);
        // 更新数量用
        List<InvoiceOrderDetailSDO> updateOrderDetailList = new ArrayList<>();
        //通知调拨单创建的货品列表
        List<AllocateOrderScItemDetailDTO> allocateOrderScItemDetailDTOS = new ArrayList<>();
        returnOrderGoodsInfos.stream().forEach(new Consumer<ReturnOrderGoodsInfo>() {
            @Override
            public void accept(ReturnOrderGoodsInfo returnOrderGoodsInfo) {
                InvoiceOrderDetailSDO tmp = itemMap.get(returnOrderGoodsInfo.getId());
                if (tmp == null) {
                    throw new FacadeException("OTS-03-003-15-005", returnOrderGoodsInfo.getId());
                }

//                Integer returnQuantity = StringUtils.isNotEmpty(tmp.getReturnQuantity())?Integer.valueOf(tmp.getReturnQuantity()):0;
                // 需要转换成小数
                String returnQuantity = InfoUtil.trim(tmp.getReturnQuantity());
//                Integer quantity = StringUtils.isNotEmpty(tmp.getQuantity())?Integer.valueOf(tmp.getQuantity()):0;
                String quantity = InfoUtil.trim(tmp.getQuantity());
                //如果退货数量大于
                if (returnOrderGoodsInfo.getReturnNum() > InfoUtil.getDoubleSubtract(quantity,returnQuantity)) {
                    throw new FacadeException("OTS-03-003-15-003");
                }
                AllocateOrderScItemDetailDTO scItemDetailDTO = new AllocateOrderScItemDetailDTO();
                String goodsId = goodsList.get(SapAndCrmFieldDealUtils.generateIdField(tmp.getScItemId())).getScItemId();
                scItemDetailDTO.setGoodsId(goodsId);
                scItemDetailDTO.setScItemId(goodsId);
                scItemDetailDTO.setScItemCode(SapAndCrmFieldDealUtils.generateIdField(tmp.getScItemId()));
                scItemDetailDTO.setQuantity(String.valueOf(returnOrderGoodsInfo.getReturnNum()));
                scItemDetailDTO.setConfirmQuantity(String.valueOf(returnOrderGoodsInfo.getReturnNum()));
                scItemDetailDTO.setInvoiceId(String.valueOf(tmp.getId()));
                scItemDetailDTO.setInvoiceNo(returnOrderRequest.getInvoiceId());
                scItemDetailDTO.setInvoiceLineNo(String.valueOf(tmp.getOrderLineId()));
                scItemDetailDTO.setExpectedProduceDate(TimeUtil.parseYYYY_MM_dd(
                        returnOrderGoodsInfo.getExpectedProductDate()
                ));
                scItemDetailDTO.setRemarks(returnOrderGoodsInfo.getRemark());
//                Integer returnQuantityNew = returnQuantity + returnOrderGoodsInfo.getReturnNum();

                String returnQuantityNew = InfoUtil.add(returnQuantity,returnOrderGoodsInfo.getReturnNum());

                tmp.setReturnQuantity(returnQuantityNew);
//                tmp.setReturnQuantity(returnQuantityNew.toString());
                updateOrderDetailList.add(tmp);
                allocateOrderScItemDetailDTOS.add(scItemDetailDTO);
            }
        });
        //获取调拨单
        if( item.get(0)==null){
            throw new FacadeException("OTS-03-003-15-004");
        }
        String allocatedOrderId = item.get(0).getSourceOrderId();
        AllocateOrderReturnOrderRequest allocateOrderReturnOrderRequest = new AllocateOrderReturnOrderRequest();
        allocateOrderReturnOrderRequest.setAllocateOrderId(allocatedOrderId);
        allocateOrderReturnOrderRequest.setAllocateOrderScItemDetailDTOS(allocateOrderScItemDetailDTOS);
        allocateOrderReturnOrderRequest.setOrderReason(returnOrderRequest.getReasonId());
        innerParam.setAllocateOrderReturnOrderRequest(allocateOrderReturnOrderRequest);
        innerParam.setUpdateOrderDetailList(updateOrderDetailList);
        return innerParam;
    }

    /**
     * 内部传参用
     */
    private class InnerParam {
        private AllocateOrderReturnOrderRequest allocateOrderReturnOrderRequest;
        private List<InvoiceOrderDetailSDO> updateOrderDetailList;

        public AllocateOrderReturnOrderRequest getAllocateOrderReturnOrderRequest() {
            return allocateOrderReturnOrderRequest;
        }

        public void setAllocateOrderReturnOrderRequest(AllocateOrderReturnOrderRequest allocateOrderReturnOrderRequest) {
            this.allocateOrderReturnOrderRequest = allocateOrderReturnOrderRequest;
        }

        public List<InvoiceOrderDetailSDO> getUpdateOrderDetailList() {
            return updateOrderDetailList;
        }

        public void setUpdateOrderDetailList(List<InvoiceOrderDetailSDO> updateOrderDetailList) {
            this.updateOrderDetailList = updateOrderDetailList;
        }
    }
    public Result<Boolean> updateInvoiceOrder(InvoiceOrderCreateRequest request) {
        log.info("InvoiceOrderWriteServiceImpl updateInvoiceOrder "+JSON.toJSONString(request));
        //参数校验
        InvoiceOrderValidator.check(request);

        // 源单id  创建时间
        String sourceOrderId = request.getSourceOrderId();
        if (StringUtils.isNotBlank(sourceOrderId)) {
            // 根据源单id 查询 源单的创建时间 可能是对应销售单的，也可能对应调拨单的

            // 查询销售单是否存在
            PageQueryOrderEsListRequest pageQueryOrderEsListRequest = new PageQueryOrderEsListRequest();
            pageQueryOrderEsListRequest.setOuterId(sourceOrderId);
            Result<List<OrderPageQueryResponse>> listResult = orderQueryService.pageQueryOrderListES(pageQueryOrderEsListRequest);
            if (listResult != null && listResult.isSuccess() && !CollectionUtils.isEmpty(listResult.getResult())) {
                OrderPageQueryResponse orderPageQueryResponse = listResult.getResult().get(0);
                request.setSourceOrderCreateTime(OtsDateUtils.parseDate(orderPageQueryResponse.getOrderTime(), "yyyy-MM-dd HH:mm:ss"));
            }
            // 查询调拨单是否存在
            AllocateOrderLoadListRequest allocateOrderLoadListRequest = new AllocateOrderLoadListRequest();
            allocateOrderLoadListRequest.setOutAllocateOrderId(sourceOrderId);
            Result<List<AllocateOrder>> loadAllocateOrderList = allocateOrderService.loadAllocateOrderList(allocateOrderLoadListRequest);
            if (loadAllocateOrderList != null && !CollectionUtils.isEmpty(loadAllocateOrderList.getResult())) {
                AllocateOrder allocateOrder = loadAllocateOrderList.getResult().get(0);
                request.setSourceOrderCreateTime(allocateOrder.getGmt_create());
            }
        }

        InvoiceOrderEntity entity = InvoiceOrderFactory.create(request);
        entity.update();
        //发送创建消息消息，订单接收
        try {
            InvoiceOrderSDO invoiceOrderSDO = entity.getInvoiceOrderSDO();
            List<InvoiceOrderDetailEntity> invoiceOrderDetailEntityList = entity.getInvoiceOrderDetailEntityList();
            List<InvoiceOrderDetailSDO> invoiceOrderDetailSDOS =invoiceOrderDetailEntityList.stream().map(InvoiceOrderDetailEntity::getInvoiceOrderDetailSDO).collect(Collectors.toList());
            invoiceOrderSDO.setDetailList(invoiceOrderDetailSDOS);

            log.info("InvoiceOrderWriteServiceImpl send_messageKey:" + invoiceOrderSDO.getInvoiceOrderId());
            boolean sendResult = messageService.sendMessage("invoice_order_message", "CR_INVOICE_V2", "InvoiceCreated", String.valueOf(entity.getInvoiceOrderSDO().getInvoiceOrderId()), JSON.toJSONString(invoiceOrderSDO));
            log.info("InvoiceOrderWriteServiceImpl sendResult_messageKey:" + sendResult + invoiceOrderSDO.getInvoiceOrderId());

        } catch (Exception e) {
//            e.printStackTrace();
            log.error("InvoiceOrderWriteServiceImpl send exception messageKey:" + request.getInvoiceOrderId(),e);
        }
        return Result.success(Boolean.TRUE);
    }
}
